<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>5_this问题</title>
</head>
<body>
<button id="btn">测试</button>

<script>
  /* 
  1.我们调用的函数
    直接调用: fn()  => window / undefined
    new调用: new fn() => 新创建的实例对象
    对象调用: obj.fn() => obj
    call/apply/bind调用: fn.call/apply(obj) fn.bind(obj)() => obj
  2.回调函数
    数组遍历相关的回调 / ajax的回调 / Promise相关的回调 / 定义器的回调 => window/undefined
    DOM事件回调 => 发生事件的DOM元素
  3.例外
    箭头函数 => 没有自己的this, 只能找外部作用域的this
  */

  function fn() {
    // 'use strict'  // 开启严格模式后, 函数中所有指向window的this变为undefined
    console.log(this) 
  }
  const obj = {test: fn}
  const obj2 = {m: 1}
  // fn()

  // new fn()
  // obj.test()
  // fn.call(obj2)
  // fn.bind(obj2)()

  document.getElementById('btn').onclick = function () {
    console.log(this) // button
  }

  // 箭头函数 => 没有自己的this, 只能找外部作用域的this
  const obj3 = { // 对象不产生作用域
    test1: function () {
      console.log(this)
    },

    test2: () => {
      console.log(this)
    },

    test3: function () {
      setTimeout(function () {
        console.log(this)
      }, 1000);
    },
    test4: function () {
      // this是obj3
      setTimeout(() => {
        console.log(this) // 没有自己的this, 去外部作用域(test4)中找this
      }, 1100);
    },
    test5: () => {
      setTimeout(() => {
        console.log(this)
      }, 1100);
    },
  }
  obj3.test1()  // obj3
  obj3.test2() // window
  obj3.test3() // window
  obj3.test4() // obj3
  obj3.test5() // window


</script>
</body>
</html>